﻿#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<assert.h>

using namespace std;
// STL C++标准模板库：是C++标准库的重要组成部分
//int main()
//{
//	// 英文编码 ASCII码
//	char arr1[] = "hello world";
//
//	// Unicode统一码
//	// UTF-8：兼容ASCII码 
//	// UTF-16 UTF-32
//	// GBK：国标，使用双字节编码
//	char arr2[] = "你好";
//	arr2[3]--;
//	arr2[3]--;
//
//	arr2[3]++;
//	arr2[3]++;
//	arr2[3]++;
//
//	return 0;
//}

// string类的模板原型
// 动态增长的字符数组
//template<class T>
//class basic_string
//{
//private:
//	T* _str;
//	size_t _size;
//	size_t _capacity;
//};
// UTF-8编码方式下的string类
// typedef basic_string<char> string 重命名

void test0()
{

}
// 成员函数
void test1()
{
	//// 1.string的无参构造
	//string s1;

	//// 2.常量字符串构造
	//string s2("hello world");

	//// 3.拷贝构造
	//string s3(s2);

	//// 4.n个字符构造
	//string s4(10, '-');

	//cout << s1 << endl;
	//cout << s2 << endl;
	//cout << s3 << endl;
	//cout << s4 << endl;

	// string (const char* s); 没有explicit 存在类型转换
	string s1, s2, s3;

	// ​​​​1.C字符串赋值
	s1 = "hello world";

	// 2.string实例对象赋值
	s2 = s1;

	// 3.字符赋值
	s3 = 'a';

	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;

	// 支持以下写法
	// string (const char* s); 构造函数没有explicit 存在类型转换
	// 常量字符串"hello world" 
	// ==> 中间临时变量(拷贝原来变量的值)，对临时变量进行类型转换(const char* 转换成string) 
	// ==> 临时变量赋值给string实例对象
	string s = "hello world";
}
void test2()
{
	string s1("1234");
	// 字符串遍历
	// 1.[下标] 运算符重载operator[]（1越界检查；2返回该下标对应元素的引用）
	for (size_t i = 0; i < s1.size(); ++i)
	{
		s1[i]++;
	}
	cout << s1 << endl;

	//2.范围for(底层是迭代器 ch是元素的引用)
	for (auto& ch : s1)
	{
		ch--;
	}
	cout << s1 << endl;

	// 反转
	size_t begin = 0, end = s1.size() - 1;
	while (begin < end)
	{
		swap(s1[begin++], s1[end--]);
	}
	cout << s1 << endl;

	// 3.迭代器 Iterators
	// 通用的访问形式
	string::iterator it1 = s1.begin();
	while (it1 != s1.end())
	{
		*it1 += 1;
		++it1;
	}
	it1 = s1.begin();
	while (it1 != s1.end())
	{
		cout << *it1 << " ";
		++it1;
	}
	// 迭代器的使用
	vector<int> v;
	vector<int>::iterator vit = v.begin();
	while (vit != v.end())
	{
		cout << *vit << " ";
		++vit;
	}

}
void Print(const string& s)
{
	cout << "调用Print" << endl;
	// 正向const迭代器：限制内容只读
	string::const_iterator it = s.begin();
	while (it != s.end())
	{
		//*it += 1; 报错：常量不可被修改
		cout << *it << " ";
		++it;
	}
	cout << endl;

	// 反向const迭代器：限制内容只读
	string::const_reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
		//*it += 1; 报错：常量不可被修改
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
}
void test3()
{
	string s1("1234");
	// 正向迭代器
	string::iterator it = s1.begin();
	//while (it != s1.end())
	//{
	//	*it += 1;
	//	++it;
	//}
	//it = s1.begin();
	while (it != s1.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	// 反向迭代器
	string::reverse_iterator rit = s1.rbegin();
	//auto rit = s1.rbegin() 熟悉rbegin的返回值
	//while (rit != s1.rend())
	//{
	//	*rit -= 1;
	//	++rit;
	//}
	//rit = s1.rbegin();
	while (rit != s1.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;

	Print(s1);
}
// string类容量相关
void test4()
{
	string s("hello world");
	// 长度
	cout << s.size() << endl;
	cout << s.length() << endl;
	// 空间容量
	cout << s.capacity() << endl;
	// 所有的string对象都返回一个固定值
	string se("Good Luck");
	cout << s.max_size() << endl;
	cout << se.max_size() << endl;
	// clear 清除数据，空间是否清除库并没有规定
	se.clear();
	cout << se << endl;
	cout << se.capacity() << endl;
	// empty判空 空1非空0
	cout << s.empty() << endl;
	cout << se.empty() << endl;

	// []查找失败断言报错
	// at查找失败抛异常

}
// string扩容机制：和平台有关
void TestPushBack()
{
	string s;
	size_t sz = s.capacity();
	// reserve:提前开好空间，避免扩容，提高效率
	// reserve改变capacity
	 s.reserve(200);
	 // resize:改变string的长度
	 string s1 = "hello world";
	 cout << "s1.size()" << " " << s1.size() << endl;
	 // 1.n < 字符串长度  删除数据
	 //s1.resize(5);
	 // 2.字符串长度 < n < capacity   插入数据
	 // 没有给有效数据 默认插入\0 不可见
	 //s1.resize(15);
	 //s1.resize(15,'!');
	 // 3. n > capacity 扩容+插入数据
	 s1.resize(20, '!');

	 cout << s1.capacity() << endl;
	 cout << "resize后的:" << s1 << endl;

	cout << "making s grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}
// 修改相关
void test5()
{
	string s1 = "hello world";
	string s2("hhhhhhh");
	s1.push_back('!');
	s1.append("Good Luck!");
	s1.append(s2);
	cout << s1 << endl;

	string s3("hello");
	s3 += "!";
	s3 += s2;
	cout << s3 << endl;

}
void test6()
{
	// 尾插/尾删 push_back/pop_back
	// 头插/头删 insert/erase
	// 需要挪动数据 效率较低 不建议使用
	string s1("hello world");
	s1.insert(0, "phrase:");
	s1.insert(18, "!!");
	cout << s1 << endl;

	// 从pos位置开始，删除npos个字符 直到字符串结束
	// npos不传参时有一个缺省值（-1） 整形提升成无符号的 42亿 相当于删光
	s1.erase(13, 5);
	cout << s1 << endl;
	s1.erase(0);
	cout << s1 << endl;

	// assign 赋值:清空原来的字符串，赋值
	// 可能会发生扩容
	string s2("hello world hello world");
	string s3("I am from China");
	s2.assign(s3);
	cout << s2 << endl;

	// replace
	// 源字符串的pos位置开始向后len个字符替换成str
	// 效率不高 不推荐使用
	string s4("hello world hello world");

	s4.replace(6, 5, "China");
	cout << s4 << endl;

	// 将空格替换成%
	// 方法1：replace
	size_t pos = s4.find(' ');
	while (pos != string::npos)
	{
		s4.replace(pos, 1, "%");
		pos = s4.find(' ', pos + 1);
	}
	cout << s4 << endl;
	// 方法2：空间换时间
	string ret;
	ret.reserve(s4.size());
	for (auto ch : s4)
	{
		if (ch != ' ')
		{
			ret += ch;
		}
		else
		{
			ret += '%';
		}
	}
	cout << ret << endl;

}
void test7()
{
	string file("test.cpp");
	//c_str 返回原生的指针
	FILE* fout = fopen(file.c_str(), "r");
	assert(fout);

	char ch = fgetc(fout);
	while (ch != EOF)
	{
		cout << ch;
		ch = fgetc(fout);
	}
	fclose(fout);
	
}
void test8()
{
	string file;
	cin >> file;
	// find
	// 取出文件名称的后缀
	//size_t pos = file.find('.');
	//if (pos != string::npos)
	//{
	//	string suffix = file.substr(pos, file.size() - pos);
	//	cout << suffix << endl;
	//}
	// test.cpp.zip.tar
	// rfind
	size_t pos = file.rfind('.');
	if (pos != string::npos)
	{
		string suffix = file.substr(pos, file.size() - pos);
		cout << suffix << endl;
	}
}
void test9()
{
	// 比较操作
	string s1("1111111");
	const char* p1 = "22222222";

	cout << (s1 == p1) << endl;
	cout << (p1 == s1) << endl;

}

int main()
{
	//test1();
	//test2();
	//test3();
	//test4();
	//TestPushBack();
	//test5();
	//test6();
	//test7();
	//test8();
	//test9();
	test0();

	return 0;
}




